﻿using System;
using System.Text.RegularExpressions;

namespace AssemblerCompiler
{
    internal static class ConverterClass
    {
        public static UInt16 HexToUInt16(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 4)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            UInt16 res = 0;
            UInt16 d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                if (arg[i] >= '0' && arg[i] <= '9')
                {
                    res += (UInt16) (d * (arg[i] - '0'));
                }
                else
                {
                    res += (UInt16) (d * (arg[i] - 'A' + 10));
                }
                d *= 16;
            }
            return res;
        }

        public static UInt16 BinToUInt16(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 16)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            UInt16 res = 0;
            UInt16 d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                res += (UInt16) (d * (arg[i] - '0'));
                d *= 2;
            }
            return res;
        }

        public static UInt16 DecToUInt16(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 5)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            UInt32 res = 0;
            UInt32 d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                res += (UInt32) (d * (arg[i] - '0'));
                d *= 10;
            }
            if (res > UInt16.MaxValue)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            return (UInt16) res;
        }

        public static Byte HexToByte(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 2)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            Byte res = 0;
            Byte d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                if (arg[i] >= '0' && arg[i] <= '9')
                {
                    res += (Byte) (d * (arg[i] - '0'));
                }
                else
                {
                    res += (Byte) (d * (arg[i] - 'A' + 10));
                }
                d *= 16;
            }
            return res;
        }

        public static Byte BinToByte(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 8)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            Byte res = 0;
            Byte d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                res += (Byte) (d * (arg[i] - '0'));
                d *= 2;
            }
            return res;
        }

        public static Byte DecToByte(string arg)
        {
            arg = Regex.Replace(arg, "^0*", "");
            arg = arg.ToUpper();
            if (arg.Length == 0)
            {
                return 0;
            }
            if (arg.Length > 3)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            UInt16 res = 0;
            UInt16 d = 1;
            for (int i = arg.Length - 1; i >= 0; --i)
            {
                res += (UInt16) (d * (arg[i] - '0'));
                d *= 10;
            }
            if (res > Byte.MaxValue)
            {
                throw new ArgumentOutOfRangeException("Constant is too big!");
            }
            return (Byte) res;
        }
    }
}